/**
 * Copyright 2009 cestum.org
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.cestum.cave.presenter.wave.utils {
import org.waveprotocol.wave.model.id.IdConstants;
import org.waveprotocol.wave.model.id.IdGenerator;
import org.waveprotocol.wave.model.id.WaveId;
import org.waveprotocol.wave.model.id.WaveletId;
import org.waveprotocol.wave.model.util.Constants;

/**
 * This class is used to generate Wave and Wavelet ids.
 *
 *
 */
public final class RandomIdGenerator implements IdGenerator {

  private var base64Generator:RandomBase64Generator= new RandomBase64Generator();
  private var domain:String;

  /**
   *
   * @param domain the wave  provider domain name (e.g. acmewave.com) to
   *        associate with generated ids
   */
  public function RandomIdGenerator(domain:String) {
    this.domain = domain;
  }

  
  public function newWaveId():WaveId {
    // 72 random bits allow billions of waves per domain without probable id collisions
    return new WaveId(domain, newId(IdConstants.WAVE_PREFIX, 72));
  }

  
  public function newConversationWaveletId():WaveletId {
    // 48 random bits allow millions of wavelets per domain per wave without probable id collisions
    return new WaveletId(domain, newId(IdConstants.CONVERSATION_WAVELET_PREFIX, 48));
  }

  
  public function newConversationRootWaveletId():WaveletId {
    return new WaveletId(domain, IdConstants.CONVERSATION_ROOT_WAVELET);
  }

  /**
   * Creates a unique string id with an initial namespacing token. Generated ids
   * take the form "[namespace]+[random-token]".
   *
   * @param namespace namespacing token
   * @param randomBits the amount of randomness in the random token
   */
  private function newId(namespace:String, randomBits:int):String {
    return build(namespace, newUniqueToken(randomBits));
  }

  /**
   * @param bits minimum quantity of randomness in the token
   * @return random token
   */
  private function newUniqueToken(bits:int):String {
    var characters:int= (bits + 5) / 6;  // 6 bits per character, rounded up
    return base64Generator.next(characters);
  }

  /**
   * @return a string from a list of tokens by using
   *         {@link IdConstants#TOKEN_SEPARATOR} as delimiters.
   */
  private static function build(...tokens):String {
    return Constants.DEFAULT_ESCAPER.join(IdConstants.TOKEN_SEPARATOR, tokens);
  }
}
}